package com.guqj.nio.netty.pstack.util;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.guqj.nio.netty.pstack.pojo.NettyMessage;

/**
 * NettyMessageEncoder NettyMessage消息编码
 * 
 * @author guqj
 * @date 2016年11月25日
 */
public final class NettyMessageEncoder extends MessageToMessageEncoder<NettyMessage> {

	private NettyMarshallingEncoder nettyMarshallingEncoder;

	public NettyMessageEncoder() throws IOException {
		this.nettyMarshallingEncoder = new NettyMarshallingEncoder();
	}

	@Override
	protected void encode(ChannelHandlerContext ctx, NettyMessage msg, List<Object> out) throws Exception {
		if (msg == null || msg.getHeader() == null) {
			throw new IllegalArgumentException("the encode message is null");
		}
		ByteBuf sendBuf = Unpooled.buffer();
		sendBuf.writeInt(msg.getHeader().getCrcCode());
		sendBuf.writeInt(msg.getHeader().getLength());
		byte[] sessionId = msg.getHeader().getSessionID().getBytes("UTF-8");
		sendBuf.writeBytes(sessionId);
		sendBuf.writeByte(msg.getHeader().getType());
		sendBuf.writeByte(msg.getHeader().getPriority());
		sendBuf.writeInt(msg.getHeader().getAttachment().size());

		if (msg.getHeader().getAttachment() != null) {
			String key = null;
			byte[] keyArray = null;
			Object value = null;
			for (Map.Entry<String, Object> param : msg.getHeader().getAttachment().entrySet()) {
				key = param.getKey();
				value = param.getValue();
				if (key == null || value == null) {
					continue;
				}
				keyArray = key.getBytes("UTF-8");
				sendBuf.writeInt(keyArray.length);
				sendBuf.writeBytes(keyArray);
				nettyMarshallingEncoder.encode(value, sendBuf);
			}

			key = null;
			keyArray = null;
			value = null;
		}
		if (msg.getBody() != null) {
			nettyMarshallingEncoder.encode(msg.getBody(), sendBuf);
		} else {
			sendBuf.writeInt(0);
		}
		sendBuf.setInt(4, sendBuf.readableBytes());
	}

}
